﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using IrrlichtLime;
using IrrlichtLime.Core;
using IrrlichtLime.Scene;

using IrrKlang;

namespace BillardPHS4700
{
    class Reaction
    {
        
        public static void ReactionBallBall(Vector3Df ball1Position, Vector3Df ball2Position, int ball1, int ball2, Vector3Df[] ballLinearVelocities, Vector3Df collisionPoint)
        {
            ISoundEngine soundEngine = new ISoundEngine();
            double relativeVelocity = (ballLinearVelocities[ball1]-ballLinearVelocities[ball2]).Length;
            double intensity = 0.578 * Math.Log((relativeVelocity*relativeVelocity)/(Constants.v_Min*Constants.v_Min));
            double volume = intensity/10;
            soundEngine.SoundVolume = (float)volume;
            soundEngine.Play2D("../assets/sounds/ballball350Hz.wav");

            float epsilon = 0.95f;
            float relativeNegativeVelocity;
            float j;
            Vector3Df normalVector = new Vector3Df();
            normalVector = (collisionPoint - ball1Position) / (collisionPoint - ball1Position).Length;
            relativeNegativeVelocity =  normalVector.DotProduct(ballLinearVelocities[ball1]- ballLinearVelocities[ball2]);
            j = -((1+epsilon)*relativeNegativeVelocity)/((1/Constants.BallWeight)*2);
            
            ballLinearVelocities[ball1] = ballLinearVelocities[ball1] + (normalVector*j)/Constants.BallWeight; 
            ballLinearVelocities[ball2] = ballLinearVelocities[ball2] - (normalVector*j)/Constants.BallWeight;
            
            /*
            Matrix ball1Inertia = Constants.BallInertia();
            float[] tmp1Vector = ((collisionPoint - balls[ball1].AbsolutePosition).CrossProduct(normalVector)).Invert().ToArray();
            ball1Inertia.GetInverse().MultiplyWith1x4Matrix(tmp1Vector);
            ball1Inertia.GetInverse();
            Vector3Df angularVectorTmp1 = new Vector3Df(ball1Inertia.GetElement(0,0), ball1Inertia.GetElement(1,0), ball1Inertia.GetElement(2,0));
            ballAngularVelocities[ball1] = ballAngularVelocities[ball1] + angularVectorTmp1*j;

            Matrix ball2Inertia = Constants.BallInertia();
            float[] tmp2Vector = ((collisionPoint - balls[ball2].AbsolutePosition).CrossProduct(normalVector)).Invert().ToArray();
            ball2Inertia.GetInverse().MultiplyWith1x4Matrix(tmp2Vector);
            ball2Inertia.GetInverse();
            Vector3Df angularVectorTmp2 = new Vector3Df(ball2Inertia.GetElement(0,0), ball2Inertia.GetElement(1,0), ball2Inertia.GetElement(2,0));
            ballAngularVelocities[ball1] = ballAngularVelocities[ball1] - angularVectorTmp2*j;
             */
        }

        public static void ReactionBallWall(Vector3Df ballPosition, int ball, Vector3Df[] ballLinearVelocities, Vector3Df collisionPoint){
            ISoundEngine soundEngine = new ISoundEngine();
            double relativeVelocity = (ballLinearVelocities[ball]).Length;
            double intensity = 0.578 * Math.Log((relativeVelocity*relativeVelocity) / (Constants.v_Min*Constants.v_Min));
            double volume = intensity / 10;
            soundEngine.SoundVolume = (float)volume;
            //soundEngine.Play2D("../assets/sounds/ballWall100Hz.wav");

            float epsilon = 0.8f;
            float relativeNegativeVelocity;
            float j;
            Vector3Df normalVector = new Vector3Df();
            normalVector = (collisionPoint - ballPosition) / (collisionPoint - ballPosition).Length;
            relativeNegativeVelocity = normalVector.DotProduct(ballLinearVelocities[ball]);
            j = -((1 + epsilon) * relativeNegativeVelocity) / ((1 / Constants.BallWeight));

            ballLinearVelocities[ball] = ballLinearVelocities[ball] + (normalVector * j) / Constants.BallWeight;
            
        }

        public static Vector3Df ReactionStickBallLinear(Vector3Df collisionPosition, Vector3Df stickVelocity, Vector3Df whiteBallPosition, SceneNode whiteBall)
        {
            ISoundEngine soundEngine = new ISoundEngine();
            double relativeVelocity = (stickVelocity).Length;
            double intensity = 0.578 * Math.Log((relativeVelocity * relativeVelocity) / (Constants.v_Min * Constants.v_Min));
            double volume = intensity / 10;
            soundEngine.SoundVolume = (float)volume;
            soundEngine.Play2D("../assets/sounds/ballStick200Hz.wav");

            float epsilon = 0.2f;
            float b = collisionPosition.Z - whiteBallPosition.Z;
            double phi = Math.Asin(b / Constants.BallRadius);
            Vector3Df whiteBallVelocity = stickVelocity * (Constants.CueStickWeight * (1 + epsilon) * ((float)(Math.Cos(phi) * Math.Cos(phi)))) / (Constants.BallWeight + Constants.CueStickWeight);
            whiteBallVelocity.RotateXYby(whiteBall.Rotation.Z);
            return whiteBallVelocity;
            
        }

        public static Vector3Df ReactionStickBallAngular(Vector3Df collisionPosition, Vector3Df stickVelocity, Vector3Df whiteBallPosition)
        {
            float epsilon = 0.2f;
            float b = collisionPosition.Z - whiteBallPosition.Z;
            double phi = Math.Asin(b / Constants.BallRadius);
            //Vector3Df pointTable = new Vector3Df(collisionPosition.X, collisionPosition.Y, Constants.TableHeight);
            Vector3Df z_uni = new Vector3Df(0, 0, 1);//(collisionPosition - pointTable) / (collisionPosition - pointTable).Length;
            Vector3Df newv = Simulation.LocalCrossProd(z_uni, stickVelocity);
            Vector3Df angularVelocity = (Simulation.LocalCrossProd(z_uni, stickVelocity)) * 5 * (Constants.CueStickWeight * (1 + epsilon) * (float)(Math.Cos(phi) * Math.Sin(phi))) / (2 * (Constants.BallWeight + Constants.CueStickWeight) * Constants.BallRadius);
            return angularVelocity;
        }
    }
}
